﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections;
using Microsoft.Xna.Framework.Content;
using MobMentality.Map;

namespace MobMentality.Social
{
	abstract class Person : IPersonDraw
	{
		/*Person's Info*/
		private Vector2 position;
		private Vector2 velocity;
		private PersonType type;
		private Texture2D image;

		protected int health;

		/*Favorite Position Variables*/
		private float[,] subPositions;

		/*Behavior Variables*/
		protected float angry;
		protected float unruly;
		protected float scared;
		
		/*Fight Variables*/
		protected int attack;				//how much damage this guy inflicts
		protected int cooldown;			//how long before you can attack again
		protected int currentCooldown;	//where this person is in the cooldown
		protected float range;


		/*Mob-Related Stats*/
		public float Angry
		{
			get
			{
				return angry;
			}
		}

		public float Unruly
		{
			get
			{
				return unruly;
			}
		}

		public float Scared
		{
			get
			{
				return scared;
			}
		}

		public int Health
		{
			get
			{
				return health;
			}
		}

		/*Holds a reference to its group controller*/
		protected GroupController groupController;

		/*Most recent target the person has been sent to move/affect*/
		private Vector2 target;

		/**
		 * Default constructor, no parameters. Should probably never be called.
		 * Sets the position to (0,0)
		 * Type is set to Inciter
		 **/
		public Person() : this(PersonType.Inciter, null, Vector2.Zero, null, "") {}

		/**
		 * Constructor which takes in a type.
		 * Sets the position to (0,0)
		 **/
		public Person(PersonType type) : this(type, null, Vector2.Zero, null, "") {}

		/**
		 * Constructor which takes in a type and position.
		 **/
		public Person(PersonType type, GroupController group, Vector2 position, ContentManager content, string imageFile)
		{
			this.type = type;
			groupController = group;
			this.position = position;

			if (content != null)
			{
				this.image = content.Load<Texture2D>(imageFile);
			}
			else
			{
				this.image = null;
			}

			velocity = Vector2.Zero;
			target = new Vector2(position.X, position.Y);
			

			subPositions = new float[3, 3];
		}

		/**
		 * Sets the target position
		 **/
		public void SetTargetLocation(Vector2 target)
		{
			this.target = target;
		}

		public void Affect(Person target)
		{
			throw new NotImplementedException();
		}

		public void Move(Vector2 Direction)
		{
			velocity = Direction;
			position += velocity;
		}

		public float Range
		{
			get
			{
				return range;
			}
		}

		public Vector2 TargetPoint
		{
			get { return target; }
		}

        public PersonType Type
        {
            get { return type; }
        }

		public Vector2 MapPosition
		{
			get { return position; }
			set { position = value; }
		}

		public Vector2 Velocity
		{
			get { return velocity; }
		}

        public Team Team
        {
            get
            {
                return groupController.Team;
            }
        }

		public Point nextTile
		{
			get;
			set;
		}

		public IGroupController Group
		{
			get { return groupController; }
			set { groupController = (GroupController) value; }
		}

		public int Width
		{
			get
			{
				return image.Width;
			}
		}

		public int Height
		{
			get
			{
				return image.Height;
			}
		}

		public Point favoriteSubPosition
		{
			get
			{
				Point favorite = new Point(0,0);

				for (int row = 0; row < 3; row++)
				{
					for (int col = 0; col < 3; col++)
					{
						if (subPositions[row, col] > subPositions[favorite.Y, favorite.X])
						{
							favorite.X = col;
							favorite.Y = row;
						}
					}
				}

				return favorite;
			}
		}

		public Point currentSubPosition
		{
			get;
			set;
		}

        /*
		 * cameraPosition - Gives the offset of the user's viewport to 0,0 on the map
		 * spriteBatch - We need to pass spriteBatch down to Draw becase 
		 *	1) its faster to use one sprite batch draw
		 *	2) need to use only one sprite batch to control the order sprites are displayed in
		 */
        public void Draw(Vector2 cameraPosition, SpriteBatch spriteBatch)
        {
			Vector2 center = position - cameraPosition - new Vector2(Width/2, Height/2);
			float grayed = (1.5f - ((float)currentCooldown / (float)cooldown));
			Color drawColor = groupController.GroupColor * grayed;
			drawColor.A = 255;
			spriteBatch.Draw(image, center, drawColor);
        }

        

		internal void JoinGroup(GroupController newGroup)
		{
			groupController.RemoveMember(this);
			groupController = newGroup;
			angry += 1;
			unruly += 0.5f;
		}

		internal void Attack(Person person)
		{
			if (currentCooldown <= 0)
			{
				//do attack animation or something?
				person.Hurt(attack);
				currentCooldown = cooldown;
				subPositions[currentSubPosition.Y, currentSubPosition.X] += attack;
				unruly += 0.25f;
			}
		}

		public void Hurt(int damage)
		{
			health -= damage;
			if (health < 50)
			{
				angry -= 0.25f;
				scared += 0.3f;
			}
			else
			{
				angry += 0.75f;
			}
			subPositions[currentSubPosition.Y, currentSubPosition.X] -= damage*(8.0f / 10.0f);
		}

		internal void Update()
		{
			subPositions[currentSubPosition.Y, currentSubPosition.X] -= 1;
			if (currentCooldown > 0)
			{
				currentCooldown -= 1;
			}
		}

		internal void Heal(int healing)
		{
			health += healing;

			if (health > 50)
			{
				scared -= 0.1f;
			}
		}
	}
}
